﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint;
using System.Web.UI.WebControls.WebParts;
using Microsoft.SharePoint.WebPartPages;
using System.Data;
using System.Web;
using System.IO;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint.Utilities;
using System.Web.UI;
using System.Reflection;
using System.Xml;

namespace PS.WebParts.Rollup.Export
{    
    /// <summary>
    /// $codebehindclassname$ will return the raw xml of a webpart.
    /// </summary>    
    public class RollupDS : IHttpHandler
    {
        private class DummyPageHandlerFactory : PageHandlerFactory
        {
        }

        public void ProcessRequest(HttpContext context)
        {
            context.Response.ContentType = "text/xml";

            RollUpDsParameters param = RollUpDsParameters.GetParameters(context);

            //IHttpHandlerFactory factory = new DummyPageHandlerFactory();

            //factory.GetHandler(null, null, this.RedirectionUrl, null);

            //IHttpHandler h1 = System.Web.UI.PageParser.GetCompiledPageInstance(param.PageUrl, context.Server.MapPath(param.PageUrl), context);

            //Page pp = (Page)h1;

            RollUpDataFormWebPart rollUp = GetWebPart(param);

            if (rollUp != null)
                PrintXml(rollUp, context);
        }

        private void PrintXml(RollUpDataFormWebPart rollUp, HttpContext context)
        {
            string xml = rollUp.GetXmlData();

            context.Response.Write(xml);                                       
        }

        private RollUpDataFormWebPart GetWebPart(RollUpDsParameters param)
        {
            RollUpDataFormWebPart result = null;

            SPWeb currentWeb = SPContext.Current.Web;

            SPLimitedWebPartManager WebPartMgr = currentWeb.GetLimitedWebPartManager(param.PageUrl, PersonalizationScope.Shared);

            //WebPartManager.
            string webPartTitle = param.WebPartTitle.ToLower().Replace(" ", string.Empty);

            foreach (System.Web.UI.WebControls.WebParts.WebPart webPart in WebPartMgr.WebParts)
            {
                if (webPart is RollUpDataFormWebPart)
                {
                    #region RollUp
                    if (webPart.Title.ToLower().Replace(" ", string.Empty) == webPartTitle)
                    {
                        result = GetRollupWebPart(webPart);
                        
                        break;
                    }
                    #endregion
                }
                else if (webPart is DataFormWebPart)
                {
                    DataFormWebPart lstWebPart = (DataFormWebPart)webPart;

                    int count = lstWebPart.DataSources.Count;

                    lstWebPart.DataBind();

                    count = lstWebPart.DataSources.Count;
                }
            }

            return result;
        }

        private RollUpDataFormWebPart GetRollupWebPart(System.Web.UI.WebControls.WebParts.WebPart webPart)
        {
            RollUpDataFormWebPart dfwp = (RollUpDataFormWebPart)webPart;

            int ii = dfwp.DataSources.Count;

            //"<%@ Register TagPrefix=\"webparts\" Namespace=\"PS.WebParts\" Assembly=\"PS.WebParts.Rollup, Version=12.0.0.0, Culture=neutral, PublicKeyToken=90e3045b123af1c3\" %>";

            string dataSourceString = "<ds xmlns:sharepoint='http://www.mysite.com/'  xmlns:asp='http://www.mysite.com1/'  xmlns:cc1='http://www.mysite.com2/'>" +
                                        dfwp.DataSourcesString.Replace("<%@", "<").Replace("%>", "/>").Replace("< Register", "<Register") +
                                        "</ds>";

            XmlDocument doc = new XmlDocument();

            XmlNamespaceManager xnsm = new XmlNamespaceManager(doc.NameTable);

            xnsm.AddNamespace("sharepoint", "http://www.mysite.com/");
            xnsm.AddNamespace("asp", "http://www.mysite.com1/");
            xnsm.AddNamespace("cc1", "http://www.mysite.com2/");

            doc.LoadXml(dataSourceString);

            Dictionary<string, MySeri> prefixDic = new Dictionary<string, MySeri>();

            foreach (XmlNode node in doc.SelectNodes("//Register"))
            {
                #region Get Assemblies/Namespace
                string tagprefix = node.Attributes["TagPrefix"].Value.ToLower();

                if (!prefixDic.ContainsKey(tagprefix))
                {
                    string assemblty = node.Attributes["Assembly"].Value;
                    string namespaceName = node.Attributes["Namespace"].Value;

                    MySeri seri = new MySeri();

                    seri.Assembly = assemblty;
                    seri.NameSpace = namespaceName;

                    prefixDic.Add(tagprefix, seri);
                }
                #endregion
            }

            foreach (XmlNode node in doc.DocumentElement.ChildNodes)
            {
                #region Process node
                if (node.LocalName == "Register") continue;

                string prefix = node.Name.Split(':')[0].ToLower();

                string name = node.LocalName;

                MySeri seri = prefixDic[prefix];

                Assembly assembly = Assembly.Load(seri.Assembly);

                if (assembly == null)
                    continue;

                Type uls = assembly.GetType(seri.NameSpace + "." + name);

                object rawDS = Activator.CreateInstance(uls);

                foreach (XmlAttribute attribute in node.Attributes)
                {
                    #region Process Attributes
                    string aName = attribute.Name;

                    PropertyInfo info = uls.GetProperty(aName);

                    if (info == null) continue;

                    if (!info.CanWrite) continue;

                    object value = attribute.Value;

                    Type propertyType = info.PropertyType;

                    if (propertyType.IsEnum)
                    {
                        value = Enum.Parse(propertyType, attribute.Value);
                    }
                    else if (propertyType.IsPrimitive)
                    {
                        //value = Activator.CreateInstance(propertyType);

                        if (propertyType == typeof(Boolean))
                            value = bool.Parse(attribute.Value);
                        else if (propertyType == typeof(Int32))
                            value = int.Parse(attribute.Value);
                    }

                    info.SetValue(rawDS, value, null);
                    #endregion
                }

                foreach (XmlNode childNode in node.ChildNodes)
                {
                    #region Process Children
                    string elementName = childNode.Name;

                    if (!elementName.Contains(':'))
                    {
                        string innerXml = childNode.InnerXml;

                        PropertyInfo info = uls.GetProperty(elementName);

                        if (info == null) continue;

                        if (!info.CanWrite) continue;

                        info.SetValue(rawDS, innerXml, null);
                    }
                    else
                    {
                        // This is a control
                    }
                    #endregion
                }

                dfwp.DataSources.Add((IDataSource)rawDS);
                #endregion
            }

            return dfwp;
        }

        public class MySeri
        {
            public MySeri()
            {

            }

            public string NameSpace { get; set; }
            public string Assembly { get; set; }
        }
        public bool IsReusable
        {
            get
            {
                return false;
            }
        }

        /// <summary>
        /// Parameter wrapper
        /// </summary>
        public class RollUpDsParameters
        {
            /// <summary>
            /// Url of the page that contains the rollup webpart to be used
            /// </summary>
            public string PageUrl = string.Empty;

            /// <summary>
            /// Title of the webpart
            /// </summary>
            public string WebPartTitle = string.Empty;

            /// <summary>
            /// Elevate the datasource request
            /// </summary>
            /// <remarks>Not bein used right now</remarks>
            public bool Elevate = false;

            public static RollUpDsParameters GetParameters(HttpContext context)
            {
                RollUpDsParameters parameters = new RollUpDsParameters();

                parameters.PageUrl = context.Request.Params["pageurl"];

                parameters.WebPartTitle = context.Request.Params["webparttitle"];
                
                return parameters;
            }
        }
    }
}
